const _ = require("lodash")
const glob = require('glob')
const fs = require('fs-extra')
const path = require('path')
const urlOpt = require('url');

const { userModulesPath } = require('../config')
const { readJson, writeFile } = require('../util/fileUtil')
const { DataDefinesNodeTextMap } = require('./mockdata')
// node初始化定义的refererUrl查询对象
let refererUrlObj = {
    query:{
        queryType: 'joint'
    }
}
/**
 * 读取楼层数据
 * @param {*} floorsFile 
 * @returns 
 */
const readFloors = (floorsFile) => {
    const floorsJson = readJson(floorsFile)
    let floors = {
        "containers": [],
        "floors": [],
        "pageSet": {}
    }
    if (floorsJson) {
        floors = floorsJson
    }
    return floors
}

/**
 * 读取所有模块目录下的楼层数据
 */
const readFloorList = () => {
    const rpath = path.resolve(userModulesPath, './**/floorData.json')
    const allfiles = glob.sync(rpath)
    let allFloors = {
        "containers": [],
        "floors": [],
        "pageSet": {}
    }
    allfiles.forEach((floorPath) => {
        const floorJson = readJson(floorPath)
        if (!_.isEmpty(floorJson)) {
            allFloors.containers.push(floorJson.containers[0])
            allFloors.floors.push(floorJson.floors[0])
        }
    })
    
    return allFloors
}

/**
 * 读取所有模块下面的有效配置
 * @ctx 如果下发ctx后，表明是初始化查询的左侧模块菜单配置，这时候需要判断是isv或者joint，即9999或者101
 * @ctx.headers.referer 通过referer 认主推走共建渠道即moduleType为101，其他如果有url有明确isv就恢复默认9999
 * @returns
 */
const readModuleList = (ctx) => {
    const rpath = path.resolve(userModulesPath, './**/moduleInfo.json')
    const allfiles = glob.sync(rpath)
    // 通过referer 认主推走共建渠道即moduleType为101，其他如果有url有明确isv就恢复默认9999
    if(ctx && ctx.headers?.referer && ctx.headers?.referer !== ''){
        try {
            refererUrlObj = urlOpt.parse(ctx.headers.referer,true)
            refererUrlObj.query['queryType'] = refererUrlObj.query['queryType'] || 'joint'
        }catch (e) {
            console.log("转换异常",e)
        }
    }
    let allModules = []
    allfiles.forEach((modulePath) => {
        const moduleJson = readJson(modulePath)
        if (!_.isEmpty(moduleJson)) {
            if(ctx){
                // 默认主推走共建渠道即moduleType为101，其他如果有url有明确isv就恢复默认9999
                moduleJson.moduleType = refererUrlObj.query.queryType === 'isv' ? '9999' : '101'
            }
            allModules.push(moduleJson)
        }
    })
    const list = [
        {
            "cateId": 1,
            "categoryName": "设计师模块",
            "moduleList": allModules
        }
    ]
    return list
}

/**
 * 保存模块数据
 * @param  moduleJson 
 * @returns 
 */
const saveModuleInfo = (moduleJson) => {
    if (moduleJson && moduleJson.moduleFlag) {
        const mpath = path.resolve(userModulesPath, moduleJson.moduleFlag, 'moduleInfo.json')
        writeFile(mpath, JSON.stringify(moduleJson, null, 4))
        return true
    }
    return false
}

/**
 * 保存editPropertyJson
 * @param  editPropertyJson 
 * @returns 
 */
const saveEditPropertyJson = (moduleFlag, editPropertyJson) => {
    if (editPropertyJson && moduleFlag) {
        const mpath = path.resolve(userModulesPath, moduleFlag, 'editProperty.json')
        writeFile(mpath, JSON.stringify(editPropertyJson, null, 4))
        return true
    }
    return false
}

/**
 * 读取moduleFlag模块的配置文件
 * @returns 
 */
 const readEditPropertyJson = (moduleFlag) => {
    const rpath = path.resolve(userModulesPath, moduleFlag, 'editProperty.json')
    const editPropertyJson = readJson(rpath)
    return editPropertyJson
}

/**
 * 保存configData
 * @param  configData 
 * @returns 
 */
const saveConfigData = (moduleFlag, configData) => {
    if (configData && moduleFlag) {
        const mpath = path.resolve(userModulesPath, moduleFlag, 'configData.json')
        writeFile(mpath, JSON.stringify(configData, null, 4))
        return true
    }
    return false
}

const readConfigData = (moduleFlag) => {
    const rpath = path.resolve(userModulesPath, moduleFlag, 'configData.json')
    const json = readJson(rpath)
    return json
}

/**
 * 删除模块及相关文件
 * @param  moduleFlag
 * @param isRecycle 是否放入回收站 TODO：暂无实现
 * @returns 
 */
const deleteModule = (moduleFlag, isRecycle) => {
    if (moduleFlag) {
        const mpath = path.resolve(userModulesPath, moduleFlag)
        fs.removeSync(mpath)
        return true
    }
    return false
}

/**
 * 保存楼层数据
 * @param  floor 
 * @returns 
 */
const saveFloor = (moduleFlag, floor) => {
    if (floor && moduleFlag) {
        const mpath = path.resolve(userModulesPath, moduleFlag, 'floorData.json')
        writeFile(mpath, JSON.stringify(floor, null, 4))
        return true
    }
    return false
}

/**
 * 把水滴格式的配置项json转换成Form表单和后端支持的json格式
 * @param {*} property 
 */
const convertProperty = (property) => {
    let result = property
    if (property && property.ui) {
        const { fieldKey: name, type, requiredMsg, ui={}, ...rest } = property
        const { width, height, placeholder, type: datasource, description = {}, options = [], ...rest2 } = ui
        const { title: tip } = description
        result = {
            ...rest,
            ...rest2,
            datasource,
            name,
            type,
            tip,
            formType: {
                placeholder,
                option: options.map(i => {
                    i.text = i.label
                    return i
                })
            },
            validate: {
                must: !!requiredMsg,
                width,
                height,
            }
        }
    }
    return result
}

/**
 * 把配置项描述文件转换成模块渲染需要的配置数据结构
 * TODO：最终会通过调用后端接口实现 先mock
 * @param {*} editPropertyJson 和水滴对齐的配置项描述文件，结构基本上和java后端返回的json接近 但是需要转换才能给到配置项渲染使用
 * @return moduleConfig 最终能够渲染配置项的数据结构（java后端返回的）
 */
const editPropertyJsonToModuleConfig = (editPropertyJson) => {
    let result = null
    if (editPropertyJson) {
        const cloneJson = _.cloneDeep(editPropertyJson)
        result = cloneJson.map((tab) => {
            tab.properties = tab.properties.map((property) => {
                return convertProperty(property)
            })
            return tab
        })
    }
    return result
}

/**
 * 把配置数据转换为DataDefines的nodeText画布渲染最终数据
 * 调整字段命名，广告组商品组id,skuId需要转换为具体的图片数据，商品数据
 * TODO: 最终是调用后端接口拿到
 * @param {*} dataDefines  格式：{
        "linkTextData": {
            "text": "121122",
        },
        "lunboGoodsGroup": {
            "materialCode": "4m72LCazMQrbF",
            "moduleCreate": 1,
            "bi": 0,
            "type": "2",
            "showNum": 4
        }
    }
 * @returns 格式：[
                    {
                        "middleName": "linkTextData",
                        "middleType": "J_LINK_TEXT",
                        "name": "text",
                        "nodeText": {
                            "text": "121122",
                            "dataSourceType": 0
                        },
                        "propertyName": "显示文案",
                        "requried": true,
                        "type": "text"
                    },
                    {
                        "height": 390,
                        "max": 10,
                        "middleName": "lunboGoodsGroup",
                        "middleType": "J_ADV_MATERIAL",
                        "name": "slide_array",
                        "nodeText": {
                            "data": [
                                {
                                    "imageUrl": "//img12.conecli.com/5acf5d9fN3cd6a23c.jpg",
                                    "w": 375,
                                    "h": 187,
                                    "x": 0,
                                    "y": 0,
                                    "detail": {
                                        "configDataType": 0
                                    },
                                    "title": "1"
                                },
                                {
                                    "imageUrl": "//img13.conecli.com/5ae19e22N98569c80.jpg",
                                    "w": 375,
                                    "h": 187,
                                    "x": 0,
                                    "y": 0,
                                    "detail": {
                                        "configDataValue": {
                                            "clickUrl": "javascript:;",
                                            "venderId": 176343,
                                            "shopId": 170905
                                        },
                                        "configDataType": 12
                                    },
                                    "title": "很好的广告"
                                }
                            ],
                            "max": 4,
                            "materialType": 2,
                            "materialId": "4m72LCazMQrbF",
                            "dataSourceType": 2
                        },
                        "requried": true,
                        "type": "jsonArray",
                        "width": 960
                    }
                ]
 */
const configDataToDataDefinesNodeText = (editPropertyJson, configData) => {
    let result = []
    if (editPropertyJson && configData) {
        const names = Object.keys(configData)
        result = names.map((name) => {
            const item = configData[name]
            return generateNodeText(name, item, editPropertyJson)
        })
        result = result.filter((item) => {
            return !_.isEmpty(item)
        })
    }
    return result
}

/**
 * 生成NodeText对象
 * @param name 
 * @param {*} item 
 * @param {*} editPropertyJson 
 */
const generateNodeText = (name, item, editPropertyJson) => {
    let result = {}
    if (name && item && editPropertyJson) {
        const property = getProperty(editPropertyJson, name)
        if (property) {
            const middleType = property.ui?.type??property.datasource
            const data = getNodeTextData(middleType, item)
            let nodeText = {}
            if(typeof item == 'string'){
                nodeText = { text: item }
            }
            else{
                nodeText = { ...item, data }
            }
            result = {
                "middleName": name,
                "middleType": middleType,
                "name": name,
                "propertyName": property.title,
                "requried": !!property.requiredMsg,
                "type": property.type,
                "nodeText": nodeText,
            }
        }
    }
    return result
}

// 数据源的详细数据 比如skuid对应的商品列表，广告组对应的图片列表
const getNodeTextData = (middleType, item) => {
    let result = {}
    if (middleType && item) {
		const nodeTextData = DataDefinesNodeTextMap[middleType]?.nodeText?.data?? {}
        switch (middleType) {
            case "J_ADV_MATERIAL":
                result = nodeTextData
                break
			case "J_LINK_TEXT":
				result = nodeTextData
                break
			case "J_LINK_IMAGE":
				result = nodeTextData
                break
            default:
                break
        }
    }
    return result
}

const getProperty = (editPropertyJson, name) => {
    let result = null
	for (let property of editPropertyJson) {
		if (property.ui) {
			if(property.fieldKey == name){
				result = property
				find = true
				break
			}
		}
		else{
			if(property.name == name){
				result = property
				find = true
				break
			}
		}
	}
    return result
}

module.exports = {
    readFloors,
    readModuleList,
    saveModuleInfo,
    saveEditPropertyJson,
    readEditPropertyJson,
    saveConfigData,
    readConfigData,
    deleteModule,
    readFloorList,
    saveFloor,
    editPropertyJsonToModuleConfig,
    configDataToDataDefinesNodeText
}